package com.xs.ai.controller;

import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.vectorstore.redis.RedisVectorStore;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.LocalDate;


/**
 * @author chenjl26787
 * @version 1.0
 * @description:
 */
@Slf4j
@RestController
@CrossOrigin
public class OpenAiController  {
    private static final String DEFAULT_PROMPT =
        """
        你是京龙航空公司的客户聊天支持代理，请以活泼，友好，乐于助人的方式来
        与您的客户沟通，请讲中文。
        在办理退订业务时你需要知道用户的姓名和预定号。
        但是每次对话尽量简短，根据用户所说内容进行相关回答，不要扯东扯西，例如：用户说你好，不要提及退订或者其他业务内容。
        """;
    @Resource(name = "customVectorStore")
    private RedisVectorStore vectorStore;

    private final ChatClient dashScopeChatClient;
    //配置redis


    public OpenAiController(ChatClient.Builder chatClientBuilder) {

        this.dashScopeChatClient = chatClientBuilder
                .defaultSystem(DEFAULT_PROMPT)
                // 实现 Chat Memory 的 Advisor
                // 在使用 Chat Memory 时，需要指定对话 ID，以便 Spring AI 处理上下文。
                .defaultAdvisors(
                        new MessageChatMemoryAdvisor(new InMemoryChatMemory())  //todo 这里可能也得修改
                )
                // 实现 Logger 的 Advisor
                .defaultAdvisors(
                        new SimpleLoggerAdvisor()
                )
                // 设置 ChatClient 中 ChatModel 的 Options 参数
                .defaultOptions(
                        DashScopeChatOptions.builder()
                                .withTopP(0.7)
                                .build()
                )
                .defaultFunctions("CancelOrder")
                .build();
    }
    @CrossOrigin()
    @GetMapping(value = "/ai/generateStreamAsString",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> simpleChat(@RequestParam(value = "message", defaultValue = "讲个笑话") String message) {
        return dashScopeChatClient
                .prompt(message)
                .system(promptSystemSpec->promptSystemSpec.param("current_date", LocalDate.now().toString())) // 预设角色设置可变参数
                .advisors(
                        advisorSpec -> advisorSpec.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY,100)
                                .param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, "678")//长期记忆的大小（chatmemory中的list的大小）
                )
                .advisors(new QuestionAnswerAdvisor(vectorStore))  //todo  不知道是否会自动进行向量搜索。
                .stream()
                .content()
                .concatWith(Flux.just("[complete]")); //解决sse长链接的问题  重复发送请求
    }

}
